#include <stdio.h>
#include <string.h>

#include "collect.h"
#include "global.h"

#define _DAY_SEC            (24 * 60 * 60)      /* secs in a day */
#define _YEAR_SEC           (365 * _DAY_SEC)    /* secs in a year */
#define _FOUR_YEAR_SEC      (1461 * _DAY_SEC)   /* secs in a 4 year interval */
#define _BASE_DOW           4                   /* 01-01-70 was a Thursday */
#define _LEAP_YEAR_ADJUST   17                  /* Leap years 1900 - 1970 */
#define _MAX_YEAR           138                 /* 2038 is the max year */

/*
 * Macro to determine if a given year, expressed as the number of years since
 * 1900, is a leap year.
 */
#define _IS_LEAP_YEAR(y)        (((y % 4 == 0) && (y % 100 != 0)) || ((y + 1900) % 400 == 0))
/*
 * Number of leap years from 1970 up to, but not including, the specified year
 * (expressed as the number of years since 1900).
 */
#define _ELAPSED_LEAP_YEARS(y)  (((y - 1)/4) - ((y - 1)/100) + ((y + 299)/400) - _LEAP_YEAR_ADJUST)

#define BIN2BCD(x)       (((x)>9) ? ((((x)/10)<<4) | ((x)%10)) : ((x)))
#define BCD2BIN(x)       ((((x)&0xF0)>>4)*10 + ((x)&0x0F))

typedef struct {
	unsigned char sec;      // 0-59
	unsigned char min;      // 0-59
	unsigned char hour;     // 0-23
	unsigned char mday;     // 1-31
	unsigned char wday;		// 0-6
	unsigned short yday;	// 0-365
	unsigned char mon;      // 0-11
	unsigned char year;     // year-1900
} utc_time_t;

typedef union 
{
	unsigned char uc[4];
	unsigned int ul;
} varul_t;

typedef union 
{
	unsigned char uc[2];
	unsigned short us;
} varus_t;

typedef union
{
	unsigned long long int	ul;
	unsigned char uc[8];
}varull_t;


typedef union
{
	unsigned int			value;				/**< OOP_OAD_U值			*/
	struct
	{
		unsigned char		nIndex;				/**< 属性数据索引			*/
		struct
		{
			unsigned char	attID  : 5;			/**< 属性ID					*/
			unsigned char	attPro : 3;			/**< 属性标识(用于事件)		*/
		};
		unsigned short		nObjID;				/**< 对象标识				*/
	};
}OOP_OAD_U;


//extern TIME glTime;



/* Converts Gregorian date to seconds since 1970-01-01 00:00:00.
 * Assumes input in normal date format, i.e. 1980-12-31 23:59:59
 * => year=1980, mon=12, day=31, hour=23, min=59, sec=59.
 *
 * [For the Julian calendar (which was used in Russia before 1917,
 * Britain & colonies before 1752, anywhere else before 1582,
 * and is still in use by some communities) leave out the
 * -year/100+year/400 terms, and add 10.]
 *
 * This algorithm was first published by Gauss (I think).
 *
 * WARNING: this function will overflow on 2106-02-07 06:28:16 on
 * machines where long is 32-bit! (However, as time_t is signed, we
 * will already get problems at other places on 2038-01-19 03:14:08)
 */
int convert_utc_sec(const utc_time_t utm)
{
	int mon = utm.mon + 1;
    int year = utm.year + 1900;
 
	/* 1..12 -> 11,12,1..10 */
	if (0 >= (mon -= 2)) 
	{
		mon += 12;	/* Puts Feb last since it has leap day */
		year -= 1;
	}
 
	return ((((int)
		  (year/4 - year/100 + year/400 + 367*mon/12 + utm.mday) +
		  year*365 - 719499
	    )*24 + utm.hour /* now have hours */
	  )*60 + utm.min /* now have minutes */
	)*60 + utm.sec; /* finally seconds */
}

int convert_utc_tm(utc_time_t *ptm, const int tim)
{
	int _lpdays[] = {-1, 30, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
    int _days[] = {-1, 30, 58, 89, 119, 150, 180, 211, 242, 272, 303, 333, 364};
	utc_time_t utm;
	int caltim = tim;    /* calendar time to convert */
	int tmptim = 0;
	int islpyr = 0;             /* is-current-year-a-leap-year flag */
	int *mdays;                 /* pointer to days or lpdays */
	int yday = 0;				/* 目前结构没有使用 */
	
	
	memset(&utm, 0x00, sizeof(utm));
	
	if(ptm == NULL) return -1;  /* 指针为空 */
	memset(ptm, 0x00, sizeof(utc_time_t));

	if((tim < 0) || (tim > 0x7fffd27f)) return -2;  /* 时间范围超限 */
	
	/* Determine the years since 1900. Start by ignoring leap years. */
    tmptim = (caltim / _YEAR_SEC) + 70;
    caltim -= (tmptim - 70) * _YEAR_SEC;
	/* Correct for elapsed leap years */
    caltim -= (_ELAPSED_LEAP_YEARS(tmptim) * _DAY_SEC);
	/*
     * If we have underflowed the __time64_t range (i.e., if caltim < 0),
     * back up one year, adjusting the correction if necessary.
     */
    if (caltim < 0)
    {
        caltim += _YEAR_SEC;
        tmptim--;
        if (_IS_LEAP_YEAR(tmptim))
        {
            caltim += _DAY_SEC;
            islpyr++;
        }
		printf("-3--caltim: %d\n", caltim);
    }
    else
    {
        if (_IS_LEAP_YEAR(tmptim))
            islpyr++;
    }
	
	/*
     * tmptim now holds the value for tm_year. caltim now holds the
     * number of elapsed seconds since the beginning of that year.
     */
	utm.year = tmptim;
	
	/*
     * Determine days since January 1 (0 - 365). This is the tm_yday value.
     * Leave caltim with number of elapsed seconds in that day.
     */
    utm.yday = caltim / _DAY_SEC; 
	caltim -= utm.yday * _DAY_SEC;
	
    /* Determine months since January (0 - 11) and day of month (1 - 31) */
    if (islpyr)
        mdays = _lpdays;
    else
        mdays = _days;
 
    for (tmptim = 1; mdays[tmptim] < utm.yday; tmptim++);
    utm.mon = --tmptim;
    utm.mday = utm.yday - mdays[tmptim];
    /* Determine days since Sunday (0 - 6) */
    utm.wday = ((tim / _DAY_SEC) + _BASE_DOW) % 7;
    utm.hour = caltim / 3600; 
    caltim -= utm.hour * 3600;
    utm.min = caltim / 60;
    utm.sec = caltim - (utm.min) * 60;
	memcpy(ptm, &utm, sizeof(utm));
	
	return 0;
}

int get_cur_sec(void)
{
	utc_time_t temptm;

	temptm.yday = glTime.year - 1900;
	temptm.mon = glTime.month - 1;
	temptm.mday = glTime.day;
	temptm.hour = glTime.hour;
	temptm.min = glTime.minute;
	temptm.sec = glTime.second;

	return (convert_utc_sec(temptm));
}

/*
 * 时间戳转换成DataTimes类型
 */
int convert_int_datatimes(int times, unsigned char *buf)
{
	utc_time_t temptm;
	unsigned char T_Year;

	convert_utc_tm(&temptm, times);
	
	T_Year = temptm.year + 1900;        // 年

	buf[0] = (T_Year>>8)&0x00FF;
	buf[1] = T_Year&0x00FF;
	buf[2] = temptm.mon+1;   // 月
	buf[3] = temptm.mday;  // 日
	buf[4] = temptm.hour; // 时
	buf[5] = temptm.min;   // 分
	buf[6] = temptm.sec;   // 秒

	return 7;
}

/**
 * 秒、分、时、日类型周期转换成秒
 * 月返回-1，年返回-2 
*/

int convert_ti_sec(unsigned char type, unsigned short val)
{
	int Temp_sec;

	Temp_sec = 1;
	
	switch(type)
	{
		case 0x00:                   //   单位为 秒
		{
			Temp_sec = 1;
			break;
		}
		case 0x01:                   //   单位为 分
		{
			Temp_sec = 60;
			break;
		}
		case 0x02:                   //   单位为 时
		{
			Temp_sec =3600;
			break;
		}
		case 0x03:                   //   单位为 日
		{
			Temp_sec = 3600*24;
			break;
		}
		case 0x04:                   //   单位为 月
		{
			Temp_sec = -1;
			break;
		}
		case 0x05:                   //   单位为 年
		{
			Temp_sec = -2; 
			break;
		}
	}

	if(Temp_sec > 0) Temp_sec = Temp_sec * val;

	return Temp_sec;
}

unsigned short buf_to_u16(unsigned char *buf)
{
	varus_t u16;
	u16.uc[1] = buf[0];
	u16.uc[0] = buf[1];

	return u16.us;
}

unsigned int buf_to_u32(unsigned char *buf)
{
	varul_t u32;

	u32.uc[3] = buf[0];
	u32.uc[2] = buf[1];
	u32.uc[1] = buf[2];
	u32.uc[0] = buf[3];

	return u32.ul;
}

unsigned long long int buf_to_u64(unsigned char *buf)
{
	varull_t u32;

	u32.uc[7] = buf[0];
	u32.uc[6] = buf[1];
	u32.uc[5] = buf[2];
	u32.uc[4] = buf[3];
	u32.uc[3] = buf[4];
	u32.uc[2] = buf[5];
	u32.uc[1] = buf[6];
	u32.uc[0] = buf[7];

	return u32.ul;
}

int rbcd_to_i32(unsigned char *buf, int len)
{
	int i;
	int var = 0;
	unsigned char flag;

	flag = buf[len-1];
	if(flag & 0x80) buf[len-1] &= 0x7F;
	for(i=1; i<=len; i++)
	{
		var = var * 100 + BCD2BIN(buf[len - i]);
	}
	if(flag & 0x80) var = 0 - var;

	return var;
}

unsigned int rbcd_to_u32(unsigned char *buf, int len)
{
	int i;
	unsigned int var = 0;

	for(i=1; i<=len; i++)
	{
		var = var * 100 + BCD2BIN(buf[len - i]);
	}

	return var;
}

/*******************************************************
* acqFreq : 执行频率， 任务信息里面的     
* recdRow : 采集方式， 方案信息里面的
* RSDSel :  输出值，抄表方法
* RSD :     输出值，698抄表所需的RSD数据
* Count_ALL : 方法2时可以需要计算总条数
* return :  RSD数据长度
* acqFreq 和 recdRow 可以根据目前程序里面定义的结构修改
*******************************************************/
int MakeRSD(void *acqFreq, void *recdRow, unsigned char *RSDSel, unsigned char *RSD, unsigned short *Count_ALL)
{
	unsigned char FreqType = ((TI*)acqFreq)->erated;
	unsigned short FreqVal = ((TI*)acqFreq)->interval;
	unsigned char GetType = ((PARA_COLLECT_PROJECT_TBL *)recdRow)->collectType;
	int CurTimes = 0; // 当前时间
	utc_time_t CurTm;
	int rev = 0;

	*RSDSel = 0;
	*Count_ALL = 0;
	switch(GetType)
	{
		case 0x00: /* 采集当前数据 */ 
		{
			*RSDSel = 0;
			RSD[0] = 0;
			rev = 1;
			break; 
		}
		case 0x01: /* 采集上几次数据 */
		{
			*RSDSel = 9;
			RSD[0] = 9;
			RSD[1] = ((PARA_COLLECT_PROJECT_TBL*)recdRow)->collectType1_n;
			rev = 2;
			break;
		}
		case 0x02: /* 按冻结时标采集 */
		{
			int TI_Sec;

			*RSDSel = 1;
			RSD[0] = 1;
			RSD[1] = 0x20;
			RSD[2] = 0x21;
			RSD[3] = 0x02;
			RSD[4] = 0x00;
			RSD[5] = 0x1C;
			
			
			TI_Sec = convert_ti_sec(FreqType, FreqVal);

			CurTimes = get_cur_sec();			

			if(TI_Sec > 0) /* 秒、分、时、天*/
			{
				CurTimes = CurTimes - (CurTimes % TI_Sec);
				convert_int_datatimes(CurTimes, &RSD[6]);
			}
			else if(TI_Sec == -1)
			{
				convert_int_datatimes(CurTimes, &RSD[6]);
				RSD[9]  = 0x01; // 日
				RSD[10] = 0x00;
				RSD[11] = 0x00;
				RSD[12] = 0x00;
			}
			else if(TI_Sec == -2)
			{
				convert_int_datatimes(CurTimes, &RSD[6]);
				RSD[8]  = 0x01;	// 月
				RSD[9]  = 0x01; // 日
				RSD[10]  = 0x00;
				RSD[11] = 0x00;
				RSD[12] = 0x00;
			}
			else
			{
				convert_int_datatimes(CurTimes, &RSD[6]);
			}
			rev = 13;
			break;
		}
		case 0x03:
		case 0x04:
		{
			*RSDSel = 2;
			varul_t startsec;
			varul_t PlanFreqSec;
			unsigned char PlanFreqType = 0;
			unsigned short PlanFreqVal = 0;
			unsigned short LastNum  = 0;
			if(GetType == 3)
			{
				PlanFreqType = ((PARA_COLLECT_PROJECT_TBL*)recdRow)->collectType3_ti.erated;
				PlanFreqVal =  ((PARA_COLLECT_PROJECT_TBL*)recdRow)->collectType3_ti.interval;
				LastNum = 1;
			}
			else 
			{
				PlanFreqType = ((PARA_COLLECT_PROJECT_TBL*)recdRow)->collectType4_retryMetering.interval.erated;
				PlanFreqVal =  ((PARA_COLLECT_PROJECT_TBL*)recdRow)->collectType4_retryMetering.interval.interval;
				LastNum = ((PARA_COLLECT_PROJECT_TBL*)recdRow)->collectType4_retryMetering.num;
			}

			int TaskFreqSec = convert_ti_sec(FreqType, FreqVal);
			PlanFreqSec.ul = convert_ti_sec(PlanFreqType, PlanFreqVal);

			CurTimes = get_cur_sec();
			CurTimes = CurTimes - (CurTimes % PlanFreqSec.ul);
			startsec.ul = CurTimes - (TaskFreqSec * LastNum);
			*Count_ALL = (TaskFreqSec * LastNum) / PlanFreqSec.ul;

			RSD[0] = 2; 
			RSD[1] = startsec.uc[0]; 
			RSD[2] = startsec.uc[1]; 
			RSD[3] = startsec.uc[2]; 
			RSD[4] = startsec.uc[3]; 
			RSD[5] = PlanFreqSec.uc[0]; 
			RSD[6] = PlanFreqSec.uc[1]; 
			RSD[7] = PlanFreqSec.uc[2]; 			
			RSD[8] = PlanFreqSec.uc[3];		 
			RSD[9] = PlanFreqType; 
			RSD[10] = PlanFreqVal/256;
			RSD[11]= PlanFreqVal%256;
			rev = 12;
			break;
		}
		default:
			rev = -1; 
			break;
	}

	return rev;
}



unsigned int convert_oad_id_00(unsigned int oad)
{
	varul_t ID645;

	OOP_OAD_U TempOAD;

	ID645.ul = 0x0000FEFE;
	TempOAD.value = oad;

	if(0x02 == TempOAD.attID)
	{
		if(0x00 == (TempOAD.nObjID & 0x0F))
		{
				ID645.uc[3] = 0x00;
				ID645.uc[2] = (TempOAD.nObjID >> 4) & 0x0F;
				ID645.uc[1] = TempOAD.nIndex - 1;
				ID645.uc[0] = 0x00;	
		}
		else if(((TempOAD.nObjID & 0x0F) < 0x04) && ((TempOAD.nObjID & 0xF0) >= 0x10) && ((TempOAD.nObjID & 0xF0) <= 0xA0)) // 分相电能量转换 A/B/C
		{		
			ID645.uc[3] = 0x00;
			ID645.uc[2] = (TempOAD.nObjID & 0x000F) * 20 + ((TempOAD.nObjID>>4) & 0x000F);
			ID645.uc[1] = 0x00;
			ID645.uc[0] = 0x00;
		}
	} 

	return ID645.ul;
}

unsigned int convert_oad_id_10(unsigned int oad)
{
	varul_t ID645;

	OOP_OAD_U TempOAD;

	ID645.ul = 0x0000FEFE;
	TempOAD.value = oad;

	if(0x02 == TempOAD.attID)
	{
		if(0x00 == (TempOAD.nObjID & 0x0F))
		{
				ID645.uc[3] = 0x01;
				ID645.uc[2] = (TempOAD.nObjID >> 4) & 0x0F;
				ID645.uc[1] = TempOAD.nIndex - 1;
				ID645.uc[0] = 0x00;	
		}
		else if(((TempOAD.nObjID & 0x0F) < 0x04) && ((TempOAD.nObjID & 0xF0) >= 0x10) && ((TempOAD.nObjID & 0xF0) <= 0xA0)) /*  分相需量转换 A/B/C */
		{
			ID645.uc[3] = 0x01;
			ID645.uc[2] = (TempOAD.nObjID & 0x000F) * 20 + ((TempOAD.nObjID>>4) & 0x000F);
			ID645.uc[1] = 0x00;
			ID645.uc[0] = 0x00;
		}
	}


	return ID645.ul;
}

unsigned int convert_oad_id_20(unsigned int oad)
{
	varul_t ID645;

	OOP_OAD_U TempOAD;

	ID645.ul = 0x0000FEFE;
	TempOAD.value = oad;

	switch(TempOAD.nObjID)
	{
		case 0x2000: /* 电压 */
		{
			if((0x02 == TempOAD.attID) && (TempOAD.nIndex < 0x04))
			{
				ID645.ul = 0x0201FF00;
				if(0x00 != TempOAD.nIndex)
				{
					ID645.uc[1] += TempOAD.nIndex + 1;
				}
			}
			break;
		}
		case 0x2001: /* 电流 */
		{
			if((0x02 == TempOAD.attID) && (TempOAD.nIndex < 0x04))
			{
				ID645.ul = 0x0202FF00;
				if(0x00 != TempOAD.nIndex)
				{
					ID645.uc[1] += TempOAD.nIndex + 1;
				}
			}
			else if(0x04 ==TempOAD.attID)
			{
				ID645.ul = 0x02800001;
			}
			break;
		}
		case 0x2003: /* 电压电流相角 */
		{
			if((0x02 == TempOAD.attID) && (TempOAD.nIndex < 0x04))
			{
				ID645.ul = 0x0207FF00;
				if(0x00 != TempOAD.nIndex)
				{
					ID645.uc[1] += TempOAD.nIndex + 1;
				}
			}
			break;
		}
		case 0x2004: /* 有功功率 */
		{
			if((0x02 == TempOAD.attID) && (TempOAD.nIndex < 0x05))
			{
				ID645.ul = 0x0203FF00;
				if(0x00 != TempOAD.nIndex)
				{
					ID645.uc[1] += TempOAD.nIndex;
				}
			}
			break;
		}
		case 0x2005: /* 无功功率 */
		{
			if((0x02 ==TempOAD.attID) && (TempOAD.nIndex < 0x05))
			{
				ID645.ul = 0x0204FF00;
				if(0x00 != TempOAD.nIndex)
				{
					ID645.uc[1] += TempOAD.nIndex;
				}
			}
			break;
		}
		case 0x200A: /* 功率因素 */
		{
			if((0x02 == TempOAD.attID) && (TempOAD.nIndex < 0x05))
			{
				ID645.ul = 0x0206FF00;
				if(0x00 != TempOAD.nIndex)
				{
					ID645.uc[1] += TempOAD.nIndex;
				}
			}
			break;
		}
		case 0x2017:
		{
			ID645.ul = 0x02800004;
			break;
		}
	}


	return ID645.ul;
}

unsigned int convert_oad_id_50(unsigned int moad, unsigned int coad, unsigned char flag)
{
	varul_t ID645;

	ID645.ul = 0x0000FEFE; /* 不支持OAD */

	OOP_OAD_U OAD_M, OAD_C;

	OAD_M.value = moad;
	OAD_C.value = coad;

	switch(OAD_M.nObjID)
	{
		case 0x5002: /* 分钟冻结 */
		{
			unsigned char metermode = (flag >> 2) & 0x03; // 电表类型

			if(1 == (flag & 0x03))
			{
				ID645.ul = 0x06000001;
			}
			else if(2 == (flag & 0x03))
			{
				switch(OAD_C.nObjID)
				{
					case 0x2021: ID645.ul = 0x06100101; break;
					case 0x2000:
					{               
						if(0x00 == OAD_C.nIndex)
						{
							if(0x01 == metermode)
							{
								ID645.ul = 0x06100101;
							}
							else
							{
								ID645.ul = 0x061001FF;
							}
						}
						else if(OAD_C.nIndex <= 0x03)
						{
							ID645.ul = 0x06100100 | OAD_C.nIndex;
						}
						break;
					}
					case 0x2001:
					{
						if(OAD_C.attID == 0x02)
						{
							if(0x00 == OAD_C.nIndex)
							{
								if(0x01 == metermode)
								{
									ID645.ul = 0x06100201;
								}
								else
								{
									ID645.ul = 0x061002FF;
								}
							}
							else if(OAD_C.nIndex <= 0x03)
							{
								ID645.ul = 0x06100200 | OAD_C.nIndex;
							}
						}
						break;
					}
					case 0x2004:
					{
						if(0x00 == OAD_C.nIndex)
						{
							if(0x01 == metermode)
							{
								ID645.ul = 0x06100300;
							}
							else
							{
								ID645.ul = 0x061003FF;
							}
						}
						else if(OAD_C.nIndex <= 0x04)//
						{
							ID645.ul = 0x06100300 | (OAD_C.nIndex- 1);
						}
						break;
					}
					case 0x2005:
					{
						if(0x00 == OAD_C.nIndex)
						{
							if(0x01 == metermode)
							{
								ID645.ul = 0x06100400;
							}
							else
								ID645.ul = 0x061004FF;
						}
						else if(OAD_C.nIndex <= 0x04)
						{
							ID645.ul = 0x06100400 | (OAD_C.nIndex- 1);
						}	
						break;
					}
					case 0x200A: 
					{
						if(0x00 == OAD_C.nIndex)
						{
							if(0x01 == metermode)
							{
								ID645.ul = 0x06100500;
							}
							else
							{
								ID645.ul = 0x061005FF;
							}	
						}
						else if(OAD_C.nIndex <= 0x04)
						{
							ID645.ul = 0x06100500 | (OAD_C.nIndex- 1);
						}	
						break;
					}
					case 0x0010: ID645.ul = 0x06100601; break;
					case 0x0020: ID645.ul = 0x06100602; break;
					case 0x0030: ID645.ul = 0x06100603; break;
					case 0x0040: ID645.ul = 0x06100604; break;
					case 0x0050: ID645.ul = 0x06100701; break;
					case 0x0060: ID645.ul = 0x06100702; break;
					case 0x0070: ID645.ul = 0x06100703; break;
					case 0x0080: ID645.ul = 0x06100704; break;
					case 0x2017: ID645.ul = 0x06100801; break;
					case 0x2018: ID645.ul = 0x06100802; break;
				}   
				break;
			}
			else 
			{
				switch(OAD_C.nObjID)
				{
					case 0x2021: ID645.ul = 0x06010001; break;
					//第 1 类负荷记录:电压电流
					case 0x2000: 
					case 0x2001: 
					{
						if(0x02 == OAD_C.nObjID)
						{
							ID645.ul = 0x06010001; 
						}
						break;
					}
					//第 2 类负荷记录:有、无功功率
					case 0x2004:
					case 0x2005: ID645.ul = 0x06020001; break;
					//第 3 类负荷记录:功率因数
					case 0x200A: ID645.ul = 0x06030001; break;
					//第 4 类负荷记录:有、无功总电能
					case 0x0010: 
					case 0x0020:
					case 0x0030:
					case 0x0040: ID645.ul = 0x06040001; break;
					//第 5 类负荷记录:四象限无功总电能
					case 0x0050:
					case 0x0060:
					case 0x0070:
					case 0x0080: ID645.ul = 0x06050001; break;
					//第 6 类负荷记录:当前需量
					case 0x2017:
					case 0x2018: ID645.ul = 0x06060001; break;
				}
				break;
			}
			break;
		}
		case 0x5004: /* 日冻结 */
		{
			case 0x2021: ID645.ul = 0x05060001; break;
			case 0x0010: ID645.ul = 0x05060101; break;
			case 0x0020: ID645.ul = 0x05060201; break;
			case 0x0030: ID645.ul = 0x05060301; break;
			case 0x0040: ID645.ul = 0x05060401; break;
			case 0x0050: ID645.ul = 0x05060501; break;
			case 0x0060: ID645.ul = 0x05060601; break;
			case 0x0070: ID645.ul = 0x05060701; break;
			case 0x0080: ID645.ul = 0x05060801; break;
			case 0x1010: ID645.ul = 0x05060901; break;
			case 0x1020: ID645.ul = 0x05060A01; break;
			case 0x2004: ID645.ul = 0x05061001; break;
			case 0x2005: ID645.ul = 0x05061001; break;
			break;
		}
		case 0x5006: /* 月冻结 */
		{
			break;
		}
	}


	return ID645.ul;
}

unsigned int convert_oad_id(unsigned int moad, unsigned int coad, unsigned char flag)
{
	varul_t ID645;

	ID645.ul = 0x0000FEFE; /* 不支持OAD */

	OOP_OAD_U OAD_M, OAD_C;

	OAD_M.value = moad;
	OAD_C.value = coad;

	if((0xFFFFFFFF == OAD_M.value) || (1 == (flag & 0x03)) || (0x50020200 == moad))
	{
		if(0x0000 == (OAD_C.nObjID & 0xFF00))
		{
			ID645.ul = convert_oad_id_00(OAD_C.value);
		}
		else if(0x1000 == (OAD_C.nObjID & 0xFF00))
		{
			ID645.ul = convert_oad_id_10(OAD_C.value);
		}
		else if(0x2000 == (OAD_C.nObjID & 0xFF00))
		{
			ID645.ul = convert_oad_id_20(OAD_C.value);
		}
		else
		{
			switch(OAD_C.value)
			{
				case 0x40000200: ID645.ul = 0x0400010C; break;
				
			}
		}
	}
	else
	{
		if(0x5000 == (OAD_C.nObjID & 0xFF00))
		{
			convert_oad_id_50(moad, coad, flag);
		}
	}

	return ID645.ul;
}

/*
 * 645协议 加33功能 
*/
void dlt645cmd_add33(unsigned char *buf)
{
	int i, j, TLen;

	for(j=0; j<6; j++)
	{
		if(0x68 == buf[j])
			break;
	}

	TLen = buf[j+9] + 10 + j;

	for(i=10+j; i<TLen; i++)
		buf[i]=buf[i]+0x33;
}

/*
 * 645协议 减33功能 
*/
void dlt645cmd_sub33(unsigned char *buf)
{
	int i, j, TLen;

	for(j=0; j<6; j++)
	{
		if(0x68 == buf[j])
			break;
	}

	TLen = buf[j+9] + 10 + j;

	for(i=10+j; i<TLen; i++)
		buf[i]=buf[i] - 0x33;
}

/*
 * 645协议 计算校验和CS  
 * 返回: 命令长度 
*/
int dlt645cmd_madecs(unsigned char * buf)
{
	unsigned char  T_CS=0x00;
	int i, j, T_Len;

	for(j=0;j<6;j++)
	{
		if(0x68 == buf[j])
			break;
	}

	T_Len=buf[j+9]+10+j;

	for(i=j; i<T_Len; i++)
	{
		T_CS += buf[i];
	}

	buf[T_Len]   = T_CS % 256;
	buf[T_Len+1] = 0x16;

	return (T_Len+2);
}


int generate_dl645_cmd(unsigned char *addr, unsigned char addrl, unsigned int id, unsigned char *buf)
{
	int i, TS_Len;
	varul_t ID645;
	
	ID645.ul = id;

	buf[0]=0xFE;
	buf[1]=0xFE;
	buf[2]=0xFE;
	buf[3]=0xFE;
	buf[4]=0x68;

	if(0x0F == (addr[addrl-1] & 0x0F))
	{	
		for(i=1; i<=addrl; i++)
		{
			addr[addrl-i] = (addr[addrl-i]>>4) & 0x0F;
			if(i != addrl)
				addr[addrl-i] |= (addr[addrl-i-1]<<4) & 0xF0;
		}
	}

	if(addrl > 6) addrl = 6;
	

	for(i=1; i<=addrl; i++)
		buf[i+4] = addr[addrl-i];
	
	for(; i<=6; i++)
		buf[i+4] = 0x00;

	buf[11] = 0x68;
	buf[12] = 0x11;
	buf[13] = 0x04;
	buf[14] = ID645.uc[0];
	buf[15] = ID645.uc[1];
	buf[16] = ID645.uc[2];
	buf[17] = ID645.uc[3];

	dlt645cmd_add33(buf);
	
	TS_Len = dlt645cmd_madecs(buf);

	return TS_Len;
}

int generate_dl645_cmd2(unsigned char *addr, unsigned char addrl, unsigned int id, int sec, unsigned char *buf)
{
	int i, TS_Len;
	varul_t ID645;
	utc_time_t readtm;
	
	ID645.ul = id;

	buf[0]=0xFE;
	buf[1]=0xFE;
	buf[2]=0xFE;
	buf[3]=0xFE;
	buf[4]=0x68;

	if(0x0F == (addr[addrl-1] & 0x0F))
	{	
		for(i=1; i<=addrl; i++)
		{
			addr[addrl-i] = (addr[addrl-i]>>4) & 0x0F;
			if(i != addrl)
				addr[addrl-i] |= (addr[addrl-i-1]<<4) & 0xF0;
		}
	}

	if(addrl > 6) addrl = 6;
	

	for(i=1; i<=addrl; i++)
		buf[i+4] = addr[addrl-i];
	
	for(; i<=6; i++)
		buf[i+4] = 0x00;

	buf[11] = 0x68;
	buf[12] = 0x11;
	buf[13] = 0x04;
	buf[14] = ID645.uc[0];
	buf[15] = ID645.uc[1];
	buf[16] = ID645.uc[2];
	buf[17] = ID645.uc[3];

	convert_utc_tm(&readtm, sec);

	buf[18]= 0x01;				
	buf[19] = BIN2BCD(readtm.min); //分
	buf[20] = BIN2BCD(readtm.hour); //时
	buf[21] = BIN2BCD(readtm.mday);  //日
	buf[22] = BIN2BCD(readtm.mon+1);  //月
	buf[23] = BIN2BCD(readtm.year-100);//年

	dlt645cmd_add33(buf);
	
	TS_Len = dlt645cmd_madecs(buf);

	return TS_Len;
}

/*******************************************************
* 获取DLT645抄表命令
* pInfo : 信息指针
* cmd ：需要发送的抄表命令
* Return: cmd长度，小于0时为不支持命令
*******************************************************/
int ReadMeterCMD_DLT645(ReadMeterInfo *pInfo, unsigned char *cmd)
{
	unsigned int TempID = 0x0000FEFE;
	int cmdlen = 0;
	unsigned char flag = 0;
	int len = 0;

	flag = pInfo->RealTimeFlag;

	TempID = convert_oad_id(pInfo->MOAD, pInfo->COAD[pInfo->COAD_SP], flag);
	pInfo->DLT645ID = TempID;

	if(0x06000000 == (TempID & 0xFF000000))
	{
		int readsec;
		varul_t startsec, freqsec;
		startsec.uc[0] = pInfo->RSD[0];
		startsec.uc[1] = pInfo->RSD[1];
		startsec.uc[2] = pInfo->RSD[2];
		startsec.uc[3] = pInfo->RSD[3];
		freqsec.uc[0] = pInfo->RSD[4];
		freqsec.uc[1] = pInfo->RSD[5];
		freqsec.uc[2] = pInfo->RSD[6];
		freqsec.uc[3] = pInfo->RSD[7];
		readsec = startsec.ul + freqsec.ul * pInfo->Count_Cur;
		cmdlen = generate_dl645_cmd2(pInfo->TSA, pInfo->TLen, TempID, readsec, cmd);
	}
	else
	{
		cmdlen = generate_dl645_cmd(pInfo->TSA, pInfo->TLen, TempID, cmd);
	}

	return cmdlen;
}


/*
* u16 represents an unsigned 16-bit number. Adjust the typedef for
* your hardware.
* Drew D. Perkins at Carnegie Mellon University.
* Code liberally borrowed from Mohsen Banan and D. Hugh Redelmeier.
* FCS lookup table as calculated by the table generator.
*/
const unsigned short fcstab[256]={
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
//#define PPPINITFCS16 0xffff 	/* Initial FCS value */
//#define PPPGOODFCS16 0xf0b8   /* Good final FCS value */
/*
* Calculate a new fcs given the current fcs and the new data.
*/

/*计算fcs校验和
返回值:校验和
*/
unsigned short FCS16( unsigned char* buf, int len)
{
	unsigned short fcs = 0xFFFF;
	while (len--) fcs=(fcs >> 8) ^ fcstab[(fcs ^ *buf++) & 0xff];
	return (fcs^0xffff);
}

/*计算fcs校验和
并把计算好的校验和追加到buf数据的尾部
*/
void FCS16_append(unsigned char *buf, int len)
{
	varus_t fcs;
	fcs.us = FCS16(buf, len);
	buf[len] = fcs.uc[0];
	buf[len+1] = fcs.uc[1];
}

/*计算fcs校验和并比较
参数:buf 为带校验数据的通讯命令的数据域就是不包含68和16
		len为带校验数据域的总长度不包含68和16
返回值:检查校验结果，0正确 -1错误
*/
int FCS16_compare(unsigned char *buf, int len)
{
	varus_t fcs;
	fcs.us = FCS16(buf, len-2);
	if((fcs.uc[0] != buf[len-2]) || (fcs.uc[1] != buf[len-1]))
	{
		return -1;
	}

	return 0;
}

int generate_dl698_apdu(unsigned int moad, unsigned int *coad, unsigned char num, unsigned char *rsd, unsigned char flag, unsigned char *apdu, unsigned char *piid)
{
	int i;
	int len = 0;
	varul_t tempoad;
	unsigned char tempu8 = 0;

	apdu[len++] = 0x05; /* GET-Request */

	if((0xFFFFFFFF == moad) || (0 != flag) || (0 == rsd[0]))
	{
		apdu[len++] = 0x02; /* GetRequestNormalList */
	}
	else
	{
		apdu[len++] = 0x03; /* GetRequestRecord */
	}

	tempu8 = *piid; 			/* bit7（服务优先级）——0：普通优先级，1：高优先级，在应答 APDU 中，其值与请求的 APDU 相同。*/		
	tempu8++; 					/* bit6（保留）*/
	if(tempu8 > 63) tempu8 = 0;	/* （服务序号）——二进制编码表示 0…63，在应答 APDU 中, 其值与请求的 APDU 相同。*/
	*piid = tempu8;
    apdu[len++] = tempu8;
	
	if((0xFFFFFFFF == moad) || (0 != flag) || (0 == rsd[0]))
	{
		apdu[len++] = num; /* SEQUENCE */
		for(i=0; i<num; i++)
		{
			tempoad.ul = coad[i];
			apdu[len++] = tempoad.uc[3];
			apdu[len++] = tempoad.uc[2];
			apdu[len++] = tempoad.uc[1];
			apdu[len++] = tempoad.uc[0];
		}

	}
	else
	{
		tempoad.ul = moad;				/* 对象属性描述符 OAD */
		apdu[len++] = tempoad.uc[3];
		apdu[len++] = tempoad.uc[2];
		apdu[len++] = tempoad.uc[1];
		apdu[len++] = tempoad.uc[0];

		apdu[len++] = rsd[0];			/* 记录行选择描述符 RSD */
		if(rsd[0] == 1)					/* Selector1 为选择对象的指定值 */
		{
			for(i=1; i<13; i++)
				apdu[len++] = rsd[i];
		}
		else if(rsd[0] == 2)				/* Selector2 为选择对象区间内连续间隔值 */
		{
			int cursec;
			varus_t no;
			varul_t startsec, freqsec;

			startsec.uc[0] = rsd[1];
			startsec.uc[1] = rsd[2];
			startsec.uc[2] = rsd[3];
			startsec.uc[3] = rsd[4];
			freqsec.uc[0] = rsd[5];
			freqsec.uc[1] = rsd[6];
			freqsec.uc[2] = rsd[7];
			freqsec.uc[3] = rsd[8];
			no.uc[1] = rsd[11];
			no.uc[0] = rsd[12];  

			apdu[len++] = 0x20;
			apdu[len++] = 0x21;
			apdu[len++] = 0x02;
			apdu[len++] = 0x00;
			
			apdu[len++] = 0x1C;
			cursec = startsec.ul + freqsec.ul * no.us;
			len += convert_int_datatimes(cursec, &apdu[len]);
			
			apdu[len++] = 0x1C;
			cursec += freqsec.ul - 1; 	/* 减1秒处理，默认是前闭后开，现场遇到前闭后闭处理的电表 */
			len += convert_int_datatimes(cursec, &apdu[len]);

			apdu[len++] = 0x54;
			apdu[len++] = rsd[8];
			apdu[len++] = rsd[9];
			apdu[len++] = rsd[10];
		}
		else							/* Selector9 为指定选取上第 n 次记录 */
		{
			apdu[len++] = rsd[1];
		}

		apdu[len++] = num;				/* 记录列选择描述符 RCSD */
		for(i=0; i<num; i++)
		{
			tempoad.ul = coad[i];
			apdu[len++] = tempoad.uc[3];
			apdu[len++] = tempoad.uc[2];
			apdu[len++] = tempoad.uc[1];
			apdu[len++] = tempoad.uc[0];
		}
	}

	apdu[len++] = 0x00; /* GetRequestRecord */
    return len;
}


/*******************************************************
* 获取DLT698抄表命令
* pInfo : 信息指针
* cmd ：需要发送的抄表命令
* PIID ：698协议中的PIID序号，可以做应答判断使用，函数内自增管理
* Return: cmd长度，小于0时为不支持命令
*******************************************************/
int ReadMeterCMD_DLT698(ReadMeterInfo *pInfo, unsigned char *cmd, unsigned char *PIID)
{
	unsigned char apdu[512];
	static unsigned char DLT698_PIID = 0;
	int i;
	int apdu_len = 0;
	int cmd_len = 0;
	int DF_LenSP, DF_CRC1SP, DF_CRC2SP;   // 位置记录
	varus_t tempus;

	cmd_len = 4;
	for(i=0; i<4; i++)
		cmd[i] = 0xFE;
	
	cmd[cmd_len++] = 0x68;
	DF_LenSP = cmd_len;
	cmd_len += 2; 			/* 长度位置空间 */

	cmd[cmd_len++] = 0x43;
	cmd[cmd_len++] = pInfo->TLen-1;
	
	for(i=1; i<=(pInfo->TLen&0x0F); i++)
		cmd[cmd_len++] = pInfo->TSA[(pInfo->TLen&0x0F) - i];
	
	cmd[cmd_len++] = 0x10;

	DF_CRC1SP = cmd_len;
	cmd_len += 2;		/* 帧头检验空间 */

	if(0x02 == pInfo->RSD[0])
	{
		varus_t tempno;
		tempno.us = pInfo->Count_Cur;
	}

	apdu_len = generate_dl698_apdu(pInfo->MOAD, &pInfo->COAD[pInfo->COAD_SP], pInfo->COAD_RNum, pInfo->RSD, pInfo->RealTimeFlag, apdu, &DLT698_PIID);

	cmd[cmd_len++] = 0x10;
	cmd[cmd_len++] = 0x00;
	if(apdu_len < 128) 
	{
		cmd[cmd_len++] = apdu_len;
	}
	else if(apdu_len < 256)
	{
		cmd[cmd_len++] = 0x81;
		cmd[cmd_len++] = apdu_len;
	}
	else
	{
		cmd[cmd_len++] = 0x82;
		cmd[cmd_len++] = apdu_len / 256;
		cmd[cmd_len++] = apdu_len % 256;
	}

	memcpy(&cmd[cmd_len], apdu, apdu_len);
    cmd_len += apdu_len;

	cmd[cmd_len++] = 0x01;
	cmd[cmd_len++] = 0x10;
	cmd_len += 16; 			/* 随机数空间 */

	DF_CRC2SP = cmd_len;
	cmd_len += 2;			/* 帧尾检验空间 */
	cmd[cmd_len++] = 0x16;

	tempus.us = cmd_len - 6;
	cmd[DF_LenSP] = tempus.uc[0];
	cmd[DF_LenSP+1] = tempus.uc[1];

	FCS16_append(&cmd[DF_LenSP], DF_CRC1SP-DF_LenSP);
	FCS16_append(&cmd[DF_LenSP], DF_CRC2SP-DF_LenSP);

	return cmd_len;
}


/********************************************************
* buf : 电表应答数据
* data : 转换的数据内容
* return ：数据内容长度，小于0时为解析错误，具体可定义
********************************************************/
int DataAnaly645(unsigned char *buf, COLLECT_DATA *data)
{
	int i;
	int sp = 0;
	int dlen = 0;
	unsigned char *pd = buf;
	varus_t DL645_ID;
	unsigned char DL645_D3;
	unsigned char DL645_D4;
	unsigned char num = 0;

	
	dlt645cmd_sub33(buf);

	for(i=0; i<10; i++)
	{
		if(0x68 == pd[0]) break;
		pd++;
	}
	if(0xD1 == pd[8]) return -1;
	dlen = pd[9];
	pd += 10;

	DL645_D4 = pd[0];
	DL645_D3 = pd[1];
	DL645_ID.uc[0] = pd[2];
	DL645_ID.uc[1] = pd[3];
	pd += 4;
	dlen -= 4;

	switch(DL645_ID.us)
	{
		case 0x0001:
		case 0x0002:
		{
			uint64 *peq = NULL;
			if(0x0001 == DL645_ID.us) peq = data->ep;
			else peq = data->ep_;
			if(0xFF == DL645_D3)
			{
				num = dlen / 4;
				if(num > 5) num = 5;
				for(i=0; i<num; i++)
				{
					peq[i] = rbcd_to_u32(pd, 4);
					peq[i] *= 100;
					pd += 4;
				}
			}
			else if(DL645_D3 < 5)
			{
				peq[DL645_D3] = rbcd_to_u32(pd, 4);
				peq[DL645_D3] *= 100;
			}
			break;
		}
		case 0x0003:
		case 0x0004:
		{
			long long int tempi64;
			if((0xFF == DL645_D3) || (0x00 == DL645_D3))
			{
				tempi64 = rbcd_to_i32(pd, 4);
				tempi64 *= 100;
				data->eqzh[DL645_ID.us - 3] = tempi64;
			}
			break;
		}
		case 0x0005:
		case 0x0006:
		case 0x0007:
		case 0x0008:
		{
			unsigned long long int tempu64;
			if((0xFF == DL645_D3) || (0x00 == DL645_D3))
			{
				tempu64 = rbcd_to_u32(pd, 4);
				tempu64 *= 100;
				data->eq[DL645_ID.us - 5] = tempu64;
			}
			break;
		}
		case 0x0101:
		case 0x0102:
		{
			if((0xFF == DL645_D3) || (0x00 == DL645_D3))
			{
				data->demand[DL645_ID.us - 0x0101].max = rbcd_to_u32(pd, 4);
				if(pd[7] == 0xFF)
				{
					data->demand[DL645_ID.us - 0x0101].time.second = 0xFF;
					data->demand[DL645_ID.us - 0x0101].time.minute = 0xFF;
					data->demand[DL645_ID.us - 0x0101].time.hour   = 0xFF;
					data->demand[DL645_ID.us - 0x0101].time.day    = 0xFF;
					data->demand[DL645_ID.us - 0x0101].time.month  = 0xFF;
					data->demand[DL645_ID.us - 0x0101].time.year   = 0xFF;
				}
				else
				{
					data->demand[DL645_ID.us - 0x0101].time.second = 0xFF;
					data->demand[DL645_ID.us - 0x0101].time.minute = BCD2BIN(pd[3]);
					data->demand[DL645_ID.us - 0x0101].time.hour   = BCD2BIN(pd[4]);
					data->demand[DL645_ID.us - 0x0101].time.day    = BCD2BIN(pd[5]);
					data->demand[DL645_ID.us - 0x0101].time.month  = BCD2BIN(pd[6]);
					data->demand[DL645_ID.us - 0x0101].time.year   = BCD2BIN(pd[7]);
				}
				
			}
		}
		case 0x0201:
		{
			if(0xFF == DL645_D3)
			{
				num = dlen / 2;
				if(num > 3) num = 3;
				for(i=0; i<num; i++)
				{
					data->u[i] = rbcd_to_u32(pd, 2);
					pd += 2;
				}
			}
			else if((DL645_D3 < 4) && (DL645_D3 > 0))
			{
				data->u[DL645_D3-1] = rbcd_to_u32(pd, 2);
			}
			break;
		}
		case 0x0202:
		{
			if(0xFF == DL645_D3)
			{
				num = dlen / 3;
				if(num > 3) num = 3;
				for(i=0; i<num; i++)
				{
					data->i[i] = rbcd_to_i32(pd, 3);
					pd += 3;
				}
			}
			else if((DL645_D3 < 4) && (DL645_D3 > 0))
			{
				data->u[DL645_D3-1] = rbcd_to_u32(pd, 3);
			}
			break;
		}
		case 0x0203:
		case 0x0204:
		{
			int *pp = NULL;
			if(0x0203 == DL645_ID.us) pp = data->p;
			else pp = data->q;
			if(0xFF == DL645_D3)
			{
				num = dlen / 3;
				if(num > 4) num = 4;
				for(i=0; i<num; i++)
				{
					pp[i] = rbcd_to_i32(pd, 3);
					pd += 3;
				}
			}
			else if(DL645_D3 < 4)
			{
				pp[DL645_D3] = rbcd_to_u32(pd, 3);
			}
			break;
		}
		case 0x0206:
		{
			if(0xFF == DL645_D3)
			{
				num = dlen / 2;
				if(num > 4) num = 4;
				for(i=0; i<num; i++)
				{
					data->pf[i] = rbcd_to_i32(pd, 2);
					pd += 2;
				}
			}
			else if(DL645_D3 < 4)
			{
				data->pf[DL645_D3] = rbcd_to_i32(pd, 2);
			}
			break;
		}
		case 0x0207:
		{
			if(0xFF == DL645_D3)
			{
				num = dlen / 2;
				if(num > 3) num = 3;
				for(i=0; i<num; i++)
				{
					data->pg[i+3] = rbcd_to_u32(pd, 2);
					pd += 2;
				}
			}
			else if((DL645_D3 < 4) && (DL645_D3 > 0))
			{
				data->pg[DL645_D3+2] = rbcd_to_u32(pd, 2);
			}
			break;
		}
		case 0x0280:
		{
			if((0x00 == DL645_D3) && (0x01 == DL645_D4))
			{
				data->i[3] = rbcd_to_i32(pd, 3);
			}
			break;
		}
		case 0x0400:
		{
			if((0x00 == DL645_D3) && (0x0C == DL645_D4))
			{
				data->time.year = BCD2BIN(pd[6]) + 2000;
				data->time.month = BCD2BIN(pd[5]);
				data->time.day = BCD2BIN(pd[4]);
				data->time.hour = BCD2BIN(pd[2]);
				data->time.minute = BCD2BIN(pd[1]);
				data->time.second = BCD2BIN(pd[0]);
			}
			break;
		}
		case 0x0506:
		{
			switch(DL645_D3)
			{
				case 0x00:
				{
					data->time.year = BCD2BIN(pd[4]) + 2000;
					data->time.month = BCD2BIN(pd[3]);
					data->time.day = BCD2BIN(pd[2]);
					data->time.hour = BCD2BIN(pd[1]);
					data->time.minute = BCD2BIN(pd[0]);
					data->time.second = 0;
					break;
				} 
				case 0x01:
				case 0x02:
				{
					unsigned long long int *pep;
					num = dlen / 4;
					if(num > 5) num = 5;
					if(0x01 == DL645_D3) pep = data->ep;
					else pep = data->ep_;
					for(i=0; i<num; i++)
					{
						pep[i] = rbcd_to_u32(pd, 4);
						pep[i] *= 100;
						pd += 4;
					}
					break;
				}
				case 0x03:
				case 0x04:
				{
					long long int tempi64;
					
					tempi64 = rbcd_to_i32(pd, 4);
					tempi64 *= 100;
					data->eqzh[DL645_D3 - 3] = tempi64;
					break;
				}
				case 0x05:
				case 0x06:
				case 0x07:
				case 0x08:
				{
					unsigned long long int tempu64;
					tempu64 = rbcd_to_u32(pd, 4);
					tempu64 *= 100;
					data->eq[DL645_D3 - 5] = tempu64;
					break;
				}
				case 0x10:
				{
					for(i=0; i<4; i++)
					{
						data->p[i] = rbcd_to_u32(pd, 3);
						pd += 3;
					}

					for(i=0; i<4; i++)
					{
						data->q[i] = rbcd_to_u32(pd, 3);
						pd += 3;
					}
					break;
				}
			}
			break;
		}
	}
	
	return 0;
}

int get_one_date(unsigned char *buf, unsigned char *data)
{
	int i;
	int dlen = 0;
	int templen = 0;	

	switch(buf[0]) 
	{
		case 0x00:
		{
			dlen = 1;
			break;
		}
		
		case 0x01:     
		case 0x02:       
		{
			dlen = 2;
			for(i=0; i<buf[1]; i++)
			{
				if((templen = get_one_date(&buf[dlen], &buf[dlen]))  == 0)
					return 0;
				dlen += templen;
			}
			break;
		}
		case 0x03: 
		case 0x0F: 
		case 0x11:  
		case 0x16:  
		{
			dlen = 2;
			break;
		}
		case 0x04: 
		{
			dlen = 1;
			if(buf[1] < 0x80)
			{
				dlen++;
				dlen += buf[1] / 8;
				if((buf[1] % 8) != 0) dlen++;
				break;
			}
			else if(buf[1] == 0x81)
			{
				dlen += 2;
				dlen += buf[2] / 8;
				if((buf[2] % 8) != 0) dlen++;
				break;
			}
			else
			{
				dlen += 3;
				dlen += buf[2] * 32;
				dlen += buf[3] / 8;
				if((buf[3] % 8) != 0) dlen++;
				break;
			}
			break;
		}
		case 0x05:                
		case 0x06:      
		case 0x17:          
		case 0x51:       
		case 0x53:     
		{
			dlen = 5;
			break;
		}
		
		case 0x09: 
		case 0x0A:   
		case 0x0C: 
		case 0x55: 
		{
			dlen += 2;
			if(buf[1] < 0x80) dlen += buf[1];
			else if(0x81 == buf[1]) dlen += buf[2] + 1;
			else dlen += buf[2] * 256 + buf[3] + 1;;
			break;
		}
		

		case 0x10: 
		case 0x12: 
		{
			dlen = 3;
			break;
		}
		case 0x14:
		case 0x15:
		case 0x18:
		{
			dlen = 9;
			break;
		}
		case 0x19:
		{
			dlen = 11;
			break;
		}
		case 0x1A:
		case 0x5F:
		{
			dlen = 6;
			break;
		}
		case 0x1B:
		case 0x54:    
		{
			dlen = 4;
			break;
		}
		case 0x1C: 
		{
			dlen = 8;
			break;
		}
		case 0x52:
		{
			dlen = 5 + buf[5] * 4;
			break;
		}
		case 0x58:     
		{
			dlen = 2; 
			for(i=0; i<2; i++)
			{
				if((templen = get_one_date(&buf[dlen], &buf[dlen]))  == 0)
					return 0;
				dlen += templen;
			}
			break;
		}
		case 0x5B:
		{
			if(0 == buf[1]) dlen =6;
			else dlen = 7 + buf[6] * 4;
			break;
		}
		case 0x5C:
		{
			if((0 == buf[1])||(1 == buf[1]))
			{
				dlen=2;
				break;
			}
			else if(2 == buf[1])
			{
				dlen = 3 + buf[2];
				break;
			}
			else if(3 == buf[1])
			{
				dlen=3;
				for(i=0;i<buf[2];i++)
				{
					dlen += buf[dlen] + 1;
				}
				break;
			}
			else if(4 == buf[1])
			{
				dlen = 3 + buf[2] * 2;
			break;
			}
			else if(5 == buf[1])         
			{
				dlen = 3 + buf[2] * 5;
				break;
			}
			else if(6 == buf[1])         
			{
				dlen=3;
				for(i=0;i<buf[2];i++)
				{
					dlen += 2; 
					dlen += buf[dlen] + 1;
					dlen += 1;
					dlen += buf[dlen] + 1;
				}
				break;
			}
			else if(7 == buf[1])          
			{
				dlen = 3 + buf[2] * 7;
			}
			else if(8 == buf[1])
			{
				dlen = 3 + buf[2] * 2;
				break;
			}
			else if(9 == buf[1])
			{				
				dlen = 3;
				break;
			}
			else
			{
				dlen = 0;
			}
		}
		case 0x5D:
		{
			dlen = 6 + buf[5];
			break;
		}
		case 0x5E:
		{

			dlen = 10 + buf[5];
			break;
		}     
		case 0x60:
		{
			dlen = 2;
			for(i=0; i<buf[1]; i++)
			{
				if(buf[dlen] == 0x00) 
				{
					dlen += 5;
				}
				else
				{
					dlen += 5;
					dlen += 1;
					dlen += buf[dlen]*4;
				}
			}
			break;
		}
		default:
		{
			dlen = 0; 
		}
	}


	return dlen;
}

int dl698_to_data(unsigned int oad, unsigned char *buf, COLLECT_DATA *data)
{
	OOP_OAD_U uoad;
	int dlen = 0;
	int sp = 0;
	int i;
	
	uoad.value = oad;

	dlen = get_one_date(buf, buf);

	switch(uoad.nObjID)
	{
		case 0x0010:
		case 0x0020:
		{
			unsigned long long int *peq = NULL;
			unsigned long long int tempu64;

			if(0x0010 == uoad.nObjID)  peq = data->ep;
			else peq = data->ep_;
			if(0x00 == uoad.nIndex)
			{
				if(buf[sp] != 0x01) break;
				sp += 2;
				for(i=0; (i<buf[1]) && (i<5); i++)
				{
					if(0x06 == buf[sp])
					{
						sp++;
						tempu64 = buf_to_u32(&buf[sp]);
						tempu64 *= 100;
						sp += 4;
					}
					else if(0x15 == buf[sp])
					{
						sp++;
						tempu64 = buf_to_u64(&buf[sp]);
						sp+=8;
					}
					else
					{
						break;
					}

					peq[i] = tempu64;
				}
			}
			else if(uoad.nIndex <= 5)
			{
				if(0x06 == buf[sp])
				{
					sp++;
					tempu64 = buf_to_u32(&buf[sp]);
					tempu64 *= 100;
				}
				else if(0x15 == buf[sp])
				{
					sp++;
					tempu64 = buf_to_u64(&buf[sp]);
				}
				else
				{
					break;
				}
				peq[uoad.nIndex - 1] = tempu64;
			}
			break;
		}
		case 0x0030:
		case 0x0040:
		{
			long long int tempi64;
			if(0x00 == uoad.nIndex)
			{
				if(buf[sp] != 0x01) break;
				sp += 2;
				if(0x05 == buf[sp])
				{
					sp++;
					int tempi32;
					tempi32 = buf_to_u32(&buf[sp]);
					tempi64 = tempi32;
					tempi64 *= 100;
				}
				else if(0x14 == buf[sp])
				{
					sp++;
					tempi64 = buf_to_u64(&buf[sp]);
				}
				if(0x0030 == uoad.nObjID) data->eqzh[0] = tempi64;
				else data->eqzh[1] = tempi64;
			}
			else if(0x01 == uoad.nIndex)
			{
				if(0x05 == buf[sp])
				{
					sp++;
					int tempi32;
					tempi32 = buf_to_u32(&buf[sp]);
					tempi64 = tempi32;
					tempi64 *= 100;
				}
				else if(0x14 == buf[sp])
				{
					sp++;
					tempi64 = buf_to_u64(&buf[sp]);
				}
				if(0x0030 == uoad.nObjID) data->eqzh[0] = tempi64;
				else data->eqzh[1] = tempi64;
			}
			break;
		}
		case 0x0050:
		case 0x0060:
		case 0x0070:
		case 0x0080:
		{
			unsigned long long int tempu64;
			if(0x00 == uoad.nIndex)
			{
				if(buf[sp] != 0x01) break;
				sp += 2;
				if(0x06 == buf[sp])
				{
					sp++;
					tempu64 = buf_to_u32(&buf[sp]);
					tempu64 *= 100;
				}
				else if(0x15 == buf[sp])
				{
					sp++;
					tempu64 = buf_to_u64(&buf[sp]);
				}
				if(0x0050 == uoad.nObjID) data->eq[0] = tempu64;
				if(0x0060 == uoad.nObjID) data->eq[1] = tempu64;
				if(0x0070 == uoad.nObjID) data->eq[2] = tempu64;
				else data->eq[3] = tempu64;
			}
			else if(0x01 == uoad.nIndex)
			{
				if(0x06 == buf[sp])
				{
					sp++;
					tempu64 = buf_to_u32(&buf[sp]);
					tempu64 *= 100;
				}
				else if(0x15 == buf[sp])
				{
					sp++;
					tempu64 = buf_to_u64(&buf[sp]);
				}
				if(0x0050 == uoad.nObjID) data->eq[0] = tempu64;
				if(0x0060 == uoad.nObjID) data->eq[1] = tempu64;
				if(0x0070 == uoad.nObjID) data->eq[2] = tempu64;
				else data->eq[3] = tempu64;
			}
			break;
		}
		case 0x1010:
		case 0x1020:
		{
			COLLECT_DEMAND *pdemand;
			if(0x1010 == uoad.nObjID) pdemand = &data->demand[0];
			else pdemand = &data->demand[1];
			if(0x00 == uoad.nIndex)
			{
				if(buf[sp] != 0x01) break;
				sp += 2;
				if(0x06 == buf[sp])
				{
					sp++;
					pdemand->max = buf_to_u32(&buf[sp]);
					sp += 4;
				}
				if(0x1C == buf[sp])
				{
					sp++;
					if(0xFF == buf[sp])
					{
						pdemand->time.second = 0xFF;
						pdemand->time.minute = 0xFF;
						pdemand->time.hour   = 0xFF;
						pdemand->time.day    = 0xFF;
						pdemand->time.month  = 0xFF;
						pdemand->time.year   = 0xFF;
					}
					else
					{
						varus_t tempyear;
						tempyear.uc[1] = buf[sp++];
						tempyear.uc[0] = buf[sp++];
						pdemand->time.year   = tempyear.us - 2000;
						pdemand->time.month  = buf[sp++];
						pdemand->time.day    = buf[sp++];
						pdemand->time.hour   = buf[sp++];
						pdemand->time.minute = buf[sp++];
						pdemand->time.second = buf[sp++];
					}
				}
			}
			else if(0x01 == uoad.nIndex)
			{
				if(0x06 == buf[sp])
				{
					sp++;
					pdemand->max = buf_to_u32(&buf[sp]);
					sp += 4;
				}
				if(0x1C == buf[sp])
				{
					sp++;
					if(0xFF == buf[sp])
					{
						pdemand->time.second = 0xFF;
						pdemand->time.minute = 0xFF;
						pdemand->time.hour   = 0xFF;
						pdemand->time.day    = 0xFF;
						pdemand->time.month  = 0xFF;
						pdemand->time.year   = 0xFF;
					}
					else
					{
						varus_t tempyear;
						tempyear.uc[1] = buf[sp++];
						tempyear.uc[0] = buf[sp++];
						pdemand->time.year   = tempyear.us - 2000;
						pdemand->time.month  = buf[sp++];
						pdemand->time.day    = buf[sp++];
						pdemand->time.hour   = buf[sp++];
						pdemand->time.minute = buf[sp++];
						pdemand->time.second = buf[sp++];
					}
				
				}
			}
			break;
		}
		case 0x2000:
		{
			if(0x02 == uoad.attID)
			{
				if(0x00 == uoad.nIndex)
				{
					if(buf[sp] != 0x01) break;
					sp += 2;
					for(i=0; (i<buf[1]) && (i<3); i++)
					{
						if(0x12 == buf[sp])
						{
							sp++;
							data->u[i] = buf_to_u16(&buf[sp]);
							sp += 2;
						}
						else
						{
							break;
						}
					}
				}
				else if(uoad.nIndex <= 3)
				{
					if(0x12 == buf[sp])
					{
						sp++;
						data->u[uoad.nIndex-1] = buf_to_u16(&buf[sp]);
					}
				}
			}
			break;
		}
		case 0x2001:
		{
			if(0x02 == uoad.attID)
			{
				if(0x00 == uoad.nIndex)
				{
					if(buf[sp] != 0x01) break;
					sp += 2;
					for(i=0; (i<buf[1]) && (i<3); i++)
					{
						if(0x05 == buf[sp])
						{
							sp++;
							data->i[i] = buf_to_u32(&buf[sp]);
							sp += 4;
						}
						else
						{
							break;
						}
					}
				}
				else if(uoad.nIndex <= 3)
				{
					if(0x05 == buf[sp])
					{
						sp++;
						data->i[uoad.nIndex-1] = buf_to_u32(&buf[sp]);
					}
				}
			}
			else if(0x04 == uoad.attID)
			{
				if(0x05 == buf[sp])
				{
					sp++;
					data->i[3] = buf_to_u32(&buf[sp]);
				}
			}
			break;
		}
		case 0x2002:
		case 0x2003:
		{
			unsigned short *puint16 = NULL;
			puint16 = data->pg;
			if(0x2003 == uoad.nObjID) puint16 += 3;
			if(0x02 == uoad.attID)
			{
				if(0x00 == uoad.nIndex)
				{
					if(buf[sp] != 0x01) break;
					sp += 2;
					for(i=0; (i<buf[1]) && (i<3); i++)
					{
						if(0x12 == buf[sp])
						{
							sp++;
							puint16[i] = buf_to_u16(&buf[sp]);
							sp += 2;
						}
						else
						{
							break;
						}
					}
				}
				else if(uoad.nIndex <= 3)
				{
					if(0x12 == buf[sp])
					{
						sp++;
						puint16[uoad.nIndex-1] = buf_to_u16(&buf[sp]);
					}
				}
			}
			break;
		}
		case 0x2004:
		case 0x2005:
		{
			int *pint32 = NULL;
			if(0x2004 == uoad.nObjID) pint32 = data->p;
			else pint32 = data->q;

			if(0x02 == uoad.attID)
			{
				if(0x00 == uoad.nIndex)
				{
					if(buf[sp] != 0x01) break;
					sp += 2;
					for(i=0; (i<buf[1]) && (i<4); i++)
					{
						if(0x05 == buf[sp])
						{
							sp++;
							pint32[i] = buf_to_u32(&buf[sp]);
							sp += 4;
						}
						else
						{
							break;
						}
					}
				}
				else if(uoad.nIndex <= 4)
				{
					if(0x05 == buf[sp])
					{
						sp++;
						pint32[uoad.nIndex-1] = buf_to_u32(&buf[sp]);
					}
				}
			}
			break;
		}
		case 0x200A:
		{
			if(0x02 == uoad.attID)
			{
				if(0x00 == uoad.nIndex)
				{
					if(buf[sp] != 0x01) break;
					sp += 2;
					for(i=0; (i<buf[1]) && (i<4); i++)
					{
						if(0x10 == buf[sp])
						{
							sp++;
							data->pf[i] = buf_to_u16(&buf[sp]);
							sp += 2;
						}
						else
						{
							break;
						}
					}
				}
				else if(uoad.nIndex <= 4)
				{
					if(0x10 == buf[sp])
					{
						sp++;
						data->pf[uoad.nIndex-1] = buf_to_u16(&buf[sp]);
					}
				}
			}
			break;
		}
		case 0x2021:
		case 0x4000:
		{
			if(0x02 == uoad.attID)
			{
				if(0x1C == buf[sp])
				{
					data->time.year = buf_to_u16(&buf[1]);
					data->time.month = buf[3];
					data->time.day = buf[4];
					data->time.hour = buf[5];
					data->time.minute = buf[6];
					data->time.second = buf[7];
				}
			}
		}
		
		default: break;
	}
	
	return dlen;
}

int DataAnaly698(unsigned char *buf, COLLECT_DATA *data)
{
	int i;
	varus_t dlen;
	int sp = 0;
	unsigned char rtype = 0;
	unsigned char addrlen = 0;
	unsigned char *pd = NULL;
	unsigned int oadbuf[30];
	varul_t	oadul;
	unsigned char oadnum = 0;
	int templen = 0;


	pd = buf;
	dlen.us = 0;

	for(i=0; i<10; i++)
	{
		if(0x68 == pd[0]) break;
		pd++;
	}

	addrlen = pd[4] & 0x0F;

	/* 查找数据应答接口 */
	if(pd[addrlen + 9] == 0x90)
	{
		if(pd[addrlen + 11] < 0x80)
		{
			dlen.us = pd[addrlen + 11];
			pd += addrlen + 12;
		}
		else if(pd[addrlen + 11] == 0x81)
		{
			dlen.us = pd[addrlen + 12];
			pd += addrlen + 13;
		}
		else if(pd[addrlen + 11] == 0x82)
		{
			dlen.uc[1] = pd[addrlen + 12];
			dlen.uc[0] = pd[addrlen + 13];
			pd += addrlen + 14;
		}
	}
	else 
	{
		dlen.uc[0] =  pd[1];
		dlen.uc[1] =  pd[2];
		dlen.us = dlen.us - addrlen - 10;
		pd += addrlen + 9;
	}


	if(0x85 != pd[0]) return -1;
	rtype = pd[1];
	pd += 3;
	sp += 3;

	if(0x02 == rtype)
	{
		oadnum = pd[0];
		pd++;
		sp++;
		for(i=0; i<oadnum; i++)
		{
			oadul.uc[3] = pd[0];
			oadul.uc[2] = pd[1];
			oadul.uc[1] = pd[2];
			oadul.uc[0] = pd[3];
			pd += 4;
			sp += 4;
			if(pd[0] != 0x01)
			{
				pd += 2;
				sp += 2;
			}
			else
			{
				pd++;
				sp++;
				templen = dl698_to_data(oadul.ul, pd, data);
				if(templen <= 0) return -2;  
				pd += templen;
				sp += templen;
			}
			if(sp > dlen.us) return -3;
		}
	}
	else if(0x03 == rtype)
	{
		oadul.uc[3] = pd[0];
		oadul.uc[2] = pd[1];
		oadul.uc[1] = pd[2];
		oadul.uc[0] = pd[3];
		pd += 4;
		sp += 4;
		oadnum = pd[0];
		for(i=0; i<oadnum; i++)
		{
			oadul.uc[3] = pd[0];
			oadul.uc[2] = pd[1];
			oadul.uc[1] = pd[2];
			oadul.uc[0] = pd[3];
			pd += 4;
			sp += 4;
			oadbuf[i] = oadul.ul;
		}

		if((pd[0] != 0x01) || (pd[1] != 0x01))
			return -4;
		
		for(i=0; i<oadnum; i++)
		{
			templen = dl698_to_data(oadbuf[i], pd, data);
			if(templen <= 0) return -2;  
			pd += templen;
			sp += templen;
		}
		if(sp > dlen.us) return -3;
	}
	else
	{
		return -5;
	}
	
	return 0;
}

/**
 * 返回值：-1：未结束到对应应答帧
 * 		非负值：68开头位置
*/
int DLT645Analyze(ReadMeterInfo *pInfo, unsigned char *buf, int len)
{
	int i;	
	int dsp = 0;
	int rev = -1;
	unsigned char *pbuf = NULL;
	unsigned char DLen = 0;
	unsigned char FCS_CRC = 0;
	varul_t TempID;


	while(1)
	{
		for(; dsp<len; dsp++)
		{
			if(0x68 == buf[dsp])  break;
		}

		if(dsp >= len) break;
		if((len - dsp) < 10) break;

		pbuf = &buf[dsp];

		if(pbuf[7] != 0x68)
		{
			dsp++;
			continue;
		}

		if((pbuf[8]&0x91) != 0x91)
		{
			dsp++;
			continue;
		}

		DLen = pbuf[9];
		if((len - dsp) < (DLen + 12))
		{
			break;
		}

		if(pbuf[DLen+11] != 0x16)
		{
			dsp++;
			continue;
		}


		for(i=1; i<=6; i++)
		{	
			if(pbuf[i] != pInfo->TSA[6-i]) 
				break;
		}
		if(i <= 6)
		{
			dsp++;
			continue;
		}

		TempID.uc[0] = pbuf[10] - 0x33;
		TempID.uc[1] = pbuf[11] - 0x33;
		TempID.uc[2] = pbuf[12] - 0x33;
		TempID.uc[3] = pbuf[13] - 0x33;

		if(pInfo->DLT645ID != TempID.ul)
		{
			dsp++;
			continue;
		}

		FCS_CRC = 0;
		for(i=0; i<(DLen+10); i++)
		{
			FCS_CRC += pbuf[i];
		}

		if(FCS_CRC != pbuf[DLen+10])
		{
			dsp++;
			continue;
		}

		rev = dsp;
		break;
	}		
	return rev;
}

/**
 * 返回值：-1：未结束到对应应答帧
 * 		非负值：68开头位置
*/
int DLT698Analyze(ReadMeterInfo *pInfo, unsigned char *buf, int len)
{
	int i;	
	int dsp = 0;
	int rev = -1;
	unsigned char *pbuf = NULL;
	varus_t DLen, FCS_CRC;
	unsigned char addrlen;

	while(1)
	{
		for(; dsp<len; dsp++)
		{
			if(0x68 == buf[dsp])  break;
		}

		if(dsp >= len) break;
		
		pbuf = &buf[dsp];

		addrlen = (pbuf[4] & 0x0F)+1;

		if((len - dsp) < (addrlen + 8)) break;

		if(FCS16_compare(&pbuf[1], addrlen+7) < 0)
		{
			dsp++;
			continue;
		}
		
		DLen.uc[0] = pbuf[1];
		DLen.uc[1] = pbuf[2];
		if(DLen.us > 2048) 		/* 防止接受错误导致长度域错误，程序解析异常*/
		{
			dsp++;
			continue;
		}

		if((len - dsp) < (DLen.us + 2)) break;
		if(pbuf[DLen.us+1] != 0x16) 
		{
			dsp++;
			continue;
		}

		if(FCS16_compare(&pbuf[1], DLen.us) < 0)
		{
			dsp++;
			continue;
		}

		for(i=0; i<addrlen; i++)
		{
			if(pInfo->TSA[i] != pbuf[addrlen - i + 4])
				break;
		}

		if(i < addrlen)
		{
			dsp++;
			continue;
		}

		rev = dsp;
		break;
	}

	return rev;
}


/**
 * 返回值：
 * 	-1：协议不支持
 *  -2：应答数据不对应,
 *  -3: 数据处理错误
*/
int MeterAckDeal(ReadMeterInfo *pInfo, unsigned char *buf, int len)
{
	int rev;
	switch(pInfo->pro)
	{
		case 0x02: // DLT645
		{
			rev = DLT645Analyze(pInfo, buf, len);
			if(rev < 0)
			{
				rev = -2;
				break;
			}
			rev = DataAnaly645(&buf[rev], &pInfo->Data);
			if(rev < 0)
			{
				rev = -3;
			}
			break;
		}
		case 0x03: // DLT698
		{
			rev = DLT698Analyze(pInfo, buf, len);
			if(rev < 0)
			{
				rev = -2;
				break;
			}
			rev = DataAnaly698(&buf[rev], &pInfo->Data);
			if(rev < 0)
			{
				rev = -3;
			}
			break;
		}
		default:
			rev = -1;
			break;
	}

	return rev;
}